import { Injectable, Logger } from '@nestjs/common';
const Binance = require('node-binance-api');
import { ConfigService } from '../config/config.service';
import {
  MarketData,
  KlineData,
  AccountInfo,
  Position,
  OrderResult,
  OrderParams,
} from './interfaces/binance.interface';

@Injectable()
export class BinanceService {
  private readonly logger = new Logger(BinanceService.name);
  private client: any;

  constructor(private configService: ConfigService) {
    this.initializeClient();
  }

  private initializeClient() {
    const useProxy = this.configService.useProxy;
    const proxyHost = this.configService.proxyHost;
    const proxyPort = this.configService.proxyPort;
    
    console.log('BinanceService 初始化配置:', {
      useProxy,
      proxyHost,
      proxyPort,
      apiKey: this.configService.binanceApiKey ? '已配置' : '未配置',
      secretKey: this.configService.binanceSecretKey ? '已配置' : '未配置',
      demoTrading: this.configService.binanceDemoTrading
    });

    // 配置 Binance 客户端选项
    const binanceOptions = {
      APIKEY: this.configService.binanceApiKey,
      APISECRET: this.configService.binanceSecretKey,
      test: this.configService.binanceDemoTrading, // 启用模拟交易模式
      useServerTime: false, // 初始化时禁用，避免立即网络请求
      recvWindow: 60000, // 增加接收窗口时间
      verbose: false, // 减少日志输出
      reconnect: false, // 禁用自动重连，我们自己处理重试
      family: 4, // 强制使用IPv4
      timeout: 30000, // 设置超时时间
      log: (log) => {
        this.logger.debug(log); // 使用logger而不是console.log
      },
    };

    // 使用构造函数直接传递选项
    this.client = new Binance(binanceOptions);

    // 配置代理（如果启用）
    if (useProxy) {
      const proxyUrl = `http://${proxyHost}:${proxyPort}`;
      this.client.httpsProxy = proxyUrl;
      console.log('配置 Binance 客户端 HTTP 代理:', proxyUrl);
    }
    
    this.logger.log('Binance客户端初始化完成');
  }

  // 添加重试机制的通用方法
  private async executeWithRetry<T>(
    operation: () => Promise<T>,
    maxRetries: number = 3,
    delay: number = 2000
  ): Promise<T> {
    for (let i = 0; i < maxRetries; i++) {
      try {
        return await operation();
      } catch (error) {
        this.logger.warn(`操作失败，第 ${i + 1} 次尝试:`, error.message);
        
        // 检查是否是连接相关错误
        const isConnectionError = error.message.includes('ConnectTimeoutError') || 
                                 error.message.includes('fetch failed') ||
                                 error.message.includes('ECONNRESET') ||
                                 error.message.includes('ENOTFOUND') ||
                                 error.message.includes('ETIMEDOUT');
        
        if (i === maxRetries - 1) {
          // 最后一次尝试失败，如果是连接错误且使用了代理，尝试直连
          if (isConnectionError && this.configService.useProxy) {
            this.logger.error('连接超时，可能是代理问题，尝试禁用代理重试...');
            
            try {
              // 重新初始化客户端，不使用代理
              const tempClient = new Binance();
              tempClient.options({
                APIKEY: this.configService.binanceApiKey,
                APISECRET: this.configService.binanceSecretKey,
                test: this.configService.binanceDemoTrading,
                useServerTime: true,
                recvWindow: 60000,
                verbose: false,
                reconnect: false,
                family: 4,
              });
              
              // 临时替换客户端
              const originalClient = this.client;
              this.client = tempClient;
              
              const result = await operation();
              this.logger.warn('直连成功，建议检查代理配置');
              
              // 恢复原客户端
              this.client = originalClient;
              return result;
            } catch (directError) {
              this.logger.error('直连也失败，抛出原始错误');
              throw error;
            }
          }
          throw error;
        }
        
        // 如果是连接错误，在最后一次重试前尝试重新初始化客户端
        if (isConnectionError && i === maxRetries - 2) {
          this.logger.warn('连接错误，重新初始化客户端...');
          this.initializeClient();
        }
        
        // 等待后重试（指数退避）
        await new Promise(resolve => setTimeout(resolve, delay * Math.pow(2, i)));
      }
    }
  }

  // 获取当前价格
  async getCurrentPrice(symbol: string): Promise<number> {
    try {
      const prices = await this.executeWithRetry(() => this.client.futuresPrices());
      if (!prices[symbol]) {
        throw new Error(`Symbol ${symbol} not found in prices`);
      }
      return parseFloat(prices[symbol]);
    } catch (error) {
      this.logger.error(`获取${symbol}价格失败:`, error);
      throw error;
    }
  }

  // 获取24小时价格统计
  async get24hrStats(symbol: string): Promise<MarketData> {
    try {
      const allStats = await this.client.futuresDaily();
      const stats = allStats.find((stat: any) => stat.symbol === symbol);
      
      if (!stats) {
        throw new Error(`Symbol ${symbol} not found in daily stats`);
      }
      
      return {
        symbol: stats.symbol,
        price: parseFloat(stats.lastPrice),
        volume: parseFloat(stats.volume),
        high: parseFloat(stats.highPrice),
        low: parseFloat(stats.lowPrice),
        open: parseFloat(stats.openPrice),
        close: parseFloat(stats.lastPrice),
        timestamp: Date.now(),
      };
    } catch (error) {
      this.logger.error(`获取${symbol}24小时统计失败:`, error);
      throw error;
    }
  }

  // 获取K线数据
  async getKlineData(
    symbol: string,
    interval: string,
    limit: number = 100,
  ): Promise<KlineData[]> {
    try {
      
      // 使用 futuresCandles 获取K线数据，根据文档调用方式
      const klines = await this.client.futuresCandles(symbol, interval, { limit });
      
      this.logger.log(`原始K线数据类型: ${typeof klines}, 长度: ${Array.isArray(klines) ? klines.length : 'N/A'}`);
      
      if (!klines || !Array.isArray(klines)) {
        this.logger.error(`K线数据格式错误: ${JSON.stringify(klines)}`);
        throw new Error('K线数据格式错误');
      }
      
      if (klines.length === 0) {
        this.logger.warn(`没有获取到K线数据: ${symbol}`);
        return [];
      }
      
      // 打印第一条原始数据用于调试
      this.logger.log(`第一条原始K线数据: ${JSON.stringify(klines[0])}`);

      const result = klines.map((kline: any) => {
        // 检查是否为对象格式的K线数据
        if (!kline || typeof kline !== 'object') {
          this.logger.error(`K线数据项格式错误: ${JSON.stringify(kline)}`);
          return {
            openTime: 0,
            open: '0',
            high: '0',
            low: '0',
            close: '0',
            volume: '0',
            closeTime: 0,
            quoteAssetVolume: '0',
            numberOfTrades: 0,
            takerBuyBaseAssetVolume: '0',
            takerBuyQuoteAssetVolume: '0',
          };
        }
        
        // 处理对象格式的K线数据
        return {
          openTime: kline.openTime || 0,
          open: kline.open || '0',
          high: kline.high || '0',
          low: kline.low || '0',
          close: kline.close || '0',
          volume: kline.volume || '0',
          closeTime: kline.closeTime || 0,
          quoteAssetVolume: kline.quoteAssetVolume || '0',
          numberOfTrades: kline.trades || kline.numberOfTrades || 0,
          takerBuyBaseAssetVolume: kline.takerBuyBaseAssetVolume || '0',
          takerBuyQuoteAssetVolume: kline.takerBuyQuoteAssetVolume || '0',
        };
      });
      
      this.logger.log(`处理后的K线数据数量: ${result.length}`);
      this.logger.log(`第一条处理后的数据: ${JSON.stringify(result[0])}`);
      
      return result;
    } catch (error) {
      this.logger.error(`获取${symbol}K线数据失败:`, error);
      throw error;
    }
  }

  // 获取账户信息
  async getAccountInfo(): Promise<AccountInfo> {
    try {
      // node-binance-api 的 futuresAccount 方法不需要参数
      const accountInfo = await this.client.futuresAccount();

      return {
        totalWalletBalance: parseFloat(accountInfo.totalWalletBalance || '0'),
        totalUnrealizedPnl: parseFloat(accountInfo.totalUnrealizedPnl || '0'),
        totalMarginBalance: parseFloat(accountInfo.totalMarginBalance || '0'),
        totalPositionInitialMargin: parseFloat(
          accountInfo.totalPositionInitialMargin || '0',
        ),
        totalOpenOrderInitialMargin: parseFloat(
          accountInfo.totalOpenOrderInitialMargin || '0',
        ),
        totalCrossWalletBalance: parseFloat(accountInfo.totalCrossWalletBalance || '0'),
        totalCrossUnPnl: parseFloat(accountInfo.totalCrossUnPnl || '0'),
        availableBalance: parseFloat(accountInfo.availableBalance || '0'),
      };
    } catch (error) {
      this.logger.error('获取账户信息失败:', error);
      throw error;
    }
  }

  // 获取持仓信息
  async getPositions(): Promise<Position[]> {
    try {
      // node-binance-api 的 futuresPositionRisk 方法不需要参数
      const positions = await this.client.futuresPositionRisk();

      return positions
        .filter((position: any) => parseFloat(position.positionAmt) !== 0)
        .map((position: any) => ({
          symbol: position.symbol,
          positionAmt: parseFloat(position.positionAmt),
          entryPrice: parseFloat(position.entryPrice),
          markPrice: parseFloat(position.markPrice),
          unRealizedProfit: parseFloat(position.unRealizedProfit),
          liquidationPrice: parseFloat(position.liquidationPrice || '0'),
          leverage: parseFloat(position.leverage || '1'),
          maxNotionalValue: parseFloat(position.maxNotionalValue || '0'),
          marginType: position.marginType || 'cross',
          isolatedMargin: parseFloat(position.isolatedMargin || '0'),
          isAutoAddMargin: position.isAutoAddMargin === 'true',
          positionSide: position.positionSide || 'BOTH',
          notional: parseFloat(position.notional || '0'),
          isolatedWallet: parseFloat(position.isolatedWallet || '0'),
        }));
    } catch (error) {
      this.logger.error('获取持仓信息失败:', error);
      throw error;
    }
  }

  // 下单 - 使用 node-binance-api 的方法
  async placeOrder(orderParams: OrderParams): Promise<OrderResult> {
    try {
      this.logger.log(`准备下单: ${JSON.stringify(orderParams)}`);
      
      let order;
      
      // 根据订单类型使用不同的方法
      if (orderParams.type === 'MARKET') {
        if (orderParams.side === 'BUY') {
          order = await this.client.futuresMarketBuy(orderParams.symbol, orderParams.quantity);
        } else {
          order = await this.client.futuresMarketSell(orderParams.symbol, orderParams.quantity);
        }
      } else if (orderParams.type === 'LIMIT') {
        if (orderParams.side === 'BUY') {
          order = await this.client.futuresBuy('LIMIT', orderParams.symbol, orderParams.quantity, orderParams.price);
        } else {
          order = await this.client.futuresSell('LIMIT', orderParams.symbol, orderParams.quantity, orderParams.price);
        }
      } else {
        // 对于其他类型的订单，使用通用方法
        order = await this.client.futuresOrder(orderParams);
      }
      
      this.logger.log(`订单执行成功: ${order.orderId}`);
      
      return {
        orderId: order.orderId,
        symbol: order.symbol,
        status: order.status,
        clientOrderId: order.clientOrderId,
        price: order.price,
        avgPrice: order.avgPrice,
        origQty: order.origQty,
        executedQty: order.executedQty,
        cumQuote: order.cumQuote,
        timeInForce: order.timeInForce,
        type: order.type,
        reduceOnly: order.reduceOnly,
        closePosition: order.closePosition,
        side: order.side,
        positionSide: order.positionSide,
        stopPrice: order.stopPrice,
        workingType: order.workingType,
        priceProtect: order.priceProtect,
        origType: order.origType,
        updateTime: order.updateTime,
      };
    } catch (error) {
      this.logger.error('下单失败:', error);
      throw error;
    }
  }

  // 市价买入
  async marketBuy(symbol: string, quantity: number, positionSide: 'LONG' | 'SHORT' = 'LONG'): Promise<OrderResult> {
    try {
      const order = await this.client.futuresMarketBuy(symbol, quantity, {
        positionSide: positionSide
      });
      return this.formatOrderResult(order);
    } catch (error) {
      this.logger.error(`市价买入失败:`, error);
      throw error;
    }
  }

  // 市价卖出
  async marketSell(symbol: string, quantity: number, positionSide: 'LONG' | 'SHORT' = 'LONG'): Promise<OrderResult> {
    try {
      const order = await this.client.futuresMarketSell(symbol, quantity, {
        positionSide: positionSide
      });
      return this.formatOrderResult(order);
    } catch (error) {
      this.logger.error(`市价卖出失败:`, error);
      throw error;
    }
  }

  // 限价买入
  async limitBuy(symbol: string, quantity: number, price: number, positionSide: 'LONG' | 'SHORT' = 'LONG'): Promise<OrderResult> {
    try {
      const order = await this.client.futuresOrder('LIMIT', 'BUY', symbol, quantity, price, {
        positionSide: positionSide
      });
      return this.formatOrderResult(order);
    } catch (error) {
      this.logger.error(`限价买入失败:`, error);
      throw error;
    }
  }

  // 限价卖出
  async limitSell(symbol: string, quantity: number, price: number, positionSide: 'LONG' | 'SHORT' = 'LONG'): Promise<OrderResult> {
    try {
      const order = await this.client.futuresOrder('LIMIT', 'SELL', symbol, quantity, price, {
        positionSide: positionSide
      });
      return this.formatOrderResult(order);
    } catch (error) {
      this.logger.error(`限价卖出失败:`, error);
      throw error;
    }
  }

  // 设置止损单
  async setStopLoss(
    symbol: string,
    quantity: number,
    stopPrice: number,
    side: 'BUY' | 'SELL',
    positionSide: 'LONG' | 'SHORT' = 'LONG',
  ): Promise<OrderResult> {
    try {
      const order = await this.client.futuresOrder('STOP_MARKET', side, symbol, quantity, stopPrice, {
        positionSide: positionSide
      });
      return this.formatOrderResult(order);
    } catch (error) {
      this.logger.error('设置止损单失败:', error);
      throw error;
    }
  }

  // 设置止盈单
  async setTakeProfit(
    symbol: string,
    quantity: number,
    stopPrice: number,
    side: 'BUY' | 'SELL',
    positionSide: 'LONG' | 'SHORT' = 'LONG',
  ): Promise<OrderResult> {
    try {
      const order = await this.client.futuresOrder('TAKE_PROFIT_MARKET', side, symbol, quantity, stopPrice, {
        positionSide: positionSide
      });
      return this.formatOrderResult(order);
    } catch (error) {
      this.logger.error('设置止盈单失败:', error);
      throw error;
    }
  }

  // 设置杠杆
  async setLeverage(symbol: string, leverage: number): Promise<any> {
    try {
      this.logger.log(`设置杠杆: ${symbol} - ${leverage}x`);
      
      // 验证杠杆倍数范围 (Binance期货杠杆范围通常是1-125)
      if (leverage < 1 || leverage > 125) {
        throw new Error(`杠杆倍数必须在1-125之间，当前值: ${leverage}`);
      }
      
      const result = await this.executeWithRetry(() => 
        this.client.futuresLeverage(symbol, leverage)
      );
      
      this.logger.log(`✅ 杠杆设置成功: ${symbol} - ${leverage}x`);
      return result;
    } catch (error) {
      this.logger.error(`设置杠杆失败 ${symbol} ${leverage}x:`, error);
      throw error;
    }
  }

  // 设置保证金模式
  async setMarginType(symbol: string, marginType: 'ISOLATED' | 'CROSSED'): Promise<any> {
    try {
      this.logger.log(`设置保证金模式: ${symbol} - ${marginType}`);
      
      const result = await this.executeWithRetry(() => 
        this.client.futuresMarginType(symbol, marginType)
      );
      
      this.logger.log(`✅ 保证金模式设置成功: ${symbol} - ${marginType}`);
      return result;
    } catch (error) {
      this.logger.error(`设置保证金模式失败 ${symbol} ${marginType}:`, error);
      throw error;
    }
  }

  // 取消订单
  async cancelOrder(symbol: string, orderId: number): Promise<any> {
    try {
      const result = await this.client.futuresCancel(symbol, { orderId });
      this.logger.log(`订单取消成功: ${orderId}`);
      return result;
    } catch (error) {
      this.logger.error(`取消订单失败: ${orderId}`, error);
      throw error;
    }
  }

  // 获取订单状态
  async getOrderStatus(symbol: string, orderId: number): Promise<any> {
    try {
      const order = await this.client.futuresOrderStatus(symbol, { orderId });
      return order;
    } catch (error) {
      this.logger.error(`获取订单状态失败: ${orderId}`, error);
      throw error;
    }
  }

  // 格式化订单结果的辅助方法
  private formatOrderResult(order: any): OrderResult {
    return {
      orderId: order.orderId,
      symbol: order.symbol,
      status: order.status,
      clientOrderId: order.clientOrderId,
      price: order.price,
      avgPrice: order.avgPrice,
      origQty: order.origQty,
      executedQty: order.executedQty,
      cumQuote: order.cumQuote,
      timeInForce: order.timeInForce,
      type: order.type,
      reduceOnly: order.reduceOnly,
      closePosition: order.closePosition,
      side: order.side,
      positionSide: order.positionSide,
      stopPrice: order.stopPrice,
      workingType: order.workingType,
      priceProtect: order.priceProtect,
      origType: order.origType,
      updateTime: order.updateTime,
    };
  }

  // 获取服务器时间 - 用于测试连接
  async getServerTime(): Promise<number> {
    try {
      const time:any = await this.executeWithRetry(() => this.client.futuresTime());
      return time.serverTime;
    } catch (error) {
      this.logger.error('获取服务器时间失败:', error);
      throw error;
    }
  }

  // 测试连接
  async testConnection(): Promise<boolean> {
    try {
      await this.getServerTime();
      this.logger.log('Binance 连接测试成功');
      return true;
    } catch (error) {
      this.logger.error('Binance 连接测试失败:', error);
      return false;
    }
  }

  // 检查对冲模式状态
  async isHedgeModeEnabled(): Promise<boolean> {
    try {
      const result = await this.client.futuresPositionSideDual();
      return result.dualSidePosition;
    } catch (error) {
      this.logger.error('检查对冲模式状态失败:', error);
      return false;
    }
  }

  // 启用对冲模式
  async enableHedgeMode(): Promise<boolean> {
    try {
      await this.client.futuresChangePositionSideDual(true);
      this.logger.log('✅ 对冲模式已启用');
      return true;
    } catch (error) {
      this.logger.error('启用对冲模式失败:', error);
      return false;
    }
  }

  // 确保对冲模式已启用
  async ensureHedgeMode(): Promise<boolean> {
    try {
      const isEnabled = await this.isHedgeModeEnabled();
      if (!isEnabled) {
        this.logger.log('🔄 对冲模式未启用，正在启用...');
        return await this.enableHedgeMode();
      } else {
        this.logger.log('✅ 对冲模式已启用');
        return true;
      }
    } catch (error) {
      this.logger.error('确保对冲模式失败:', error);
      return false;
    }
  }
}